package com.jhgsys.internal.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jhgsys.internal.common.entity.*;
import com.jhgsys.internal.common.utils.SortUtil;
import com.jhgsys.internal.common.utils.TreeUtil;
import com.jhgsys.internal.system.entity.Dept;
import com.jhgsys.internal.system.entity.Menu;
import com.jhgsys.internal.system.mapper.DeptMapper;
import com.jhgsys.internal.system.service.IDeptService;
import com.jhgsys.internal.system.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author MrBird
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements IDeptService {

    @Autowired
    private IUserService userService;

    /**
     * 查询所有部门
     *
     * @param dept 部门
     * @return
     * @author chenx
     * @since 2019-07-18
     */
    @Override
    public List<Dept> findDeptForm(Dept dept) {
        LambdaQueryWrapper<Dept> deptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        deptLambdaQueryWrapper.eq(Dept::getDeletedFlg,FebsConstant.VALID);
        if(StringUtils.isNotBlank(dept.getTenantId())){
            deptLambdaQueryWrapper.eq(Dept::getTenantId,dept.getTenantId());
        }
        if(StringUtils.isNotBlank(dept.getDeptCode())){
            deptLambdaQueryWrapper.eq(Dept::getDeptCode,dept.getDeptCode());
        }
        if(StringUtils.isNotBlank(dept.getBusinessCode())){
            deptLambdaQueryWrapper.eq(Dept::getBusinessCode,dept.getBusinessCode());
        }
        if(StringUtils.isNotBlank(dept.getDeptName())){
            deptLambdaQueryWrapper.eq(Dept::getDeptName,dept.getDeptName());
        }
        if(StringUtils.isNotBlank(dept.getDeptType())){
            deptLambdaQueryWrapper.eq(Dept::getDeptType,dept.getDeptType());
        }
        return this.baseMapper.selectList(deptLambdaQueryWrapper);
    }

    /**
     * 分页查询
     * @param request
     * @param dept
     * @return
     */
    @Override
    public IPage<Dept> findDepts(QueryRequest request, Dept dept){
        LambdaQueryWrapper<Dept> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dept::getDeletedFlg, FebsConstant.VALID);
        if (StringUtils.isNotEmpty(dept.getDeptName())) {
            queryWrapper.like(Dept::getDeptName, dept.getDeptName());
        }
        Page<Dept> page = new Page<>(request.getPageNum(), request.getPageSize());
        SortUtil.handlePageSort(request, page, "orderNum", FebsConstant.ORDER_ASC, true);
        return this.page(page, queryWrapper);
    }

    @Override
    public Dept findDeptByDeptId(String deptId) {
        return this.baseMapper.selectById(deptId);
    }

    @Override
    public List<Dept> findDeptByDeptIds(List<String> deptIds) {
        LambdaQueryWrapper<Dept> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dept::getDeletedFlg, FebsConstant.VALID);
        queryWrapper.in(Dept::getDeptId, deptIds);
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<DeptTree<Dept>> findDepts() {
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByAsc(Dept::getOrderNum);
        queryWrapper.lambda().eq(Dept::getDeletedFlg, FebsConstant.VALID);
        List<Dept> depts = this.baseMapper.selectList(queryWrapper);
        List<DeptTree<Dept>> trees = this.convertDepts(depts);
        return TreeUtil.buildDeptTree(trees);
    }

    @Override
    public List<DeptTree<Dept>> findDepts(Dept dept) {
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(dept.getDeptName())) {
            queryWrapper.lambda().like(Dept::getDeptName, dept.getDeptName());
        }
        if (StringUtils.isNotBlank(dept.getParentId())) {
            queryWrapper.lambda().eq(Dept::getParentId, dept.getParentId());
        }
        if (StringUtils.isNotBlank(dept.getTenantId())) {
            queryWrapper.lambda().eq(Dept::getTenantId, dept.getTenantId());
        }
        if (StringUtils.isNotBlank(dept.getStatus())) {
            queryWrapper.lambda().eq(Dept::getStatus, dept.getStatus());
        }
        queryWrapper.lambda().eq(Dept::getDeletedFlg, FebsConstant.VALID);
        queryWrapper.lambda().orderByAsc(Dept::getOrderNum);
        List<Dept> depts = this.baseMapper.selectList(queryWrapper);
        List<DeptTree<Dept>> trees = this.convertDepts(depts);
        return TreeUtil.buildDeptTree(trees);
    }

    public List<DeptTreeNew<Dept>> searchDepts(Dept dept) {
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(dept.getDeptName())) {
            queryWrapper.lambda().like(Dept::getDeptName, dept.getDeptName());
        }
        if (StringUtils.isNotBlank(dept.getParentId())) {
            queryWrapper.lambda().eq(Dept::getParentId, dept.getParentId());
        }
        if (StringUtils.isNotBlank(dept.getTenantId())) {
            queryWrapper.lambda().eq(Dept::getTenantId, dept.getTenantId());
        }
        if (StringUtils.isNotBlank(dept.getStatus())) {
            queryWrapper.lambda().eq(Dept::getStatus, dept.getStatus());
        }
        queryWrapper.lambda().eq(Dept::getDeletedFlg, FebsConstant.VALID);
        queryWrapper.lambda().orderByAsc(Dept::getOrderNum);
        List<Dept> depts = this.baseMapper.selectList(queryWrapper);
        List<DeptTreeNew<Dept>> trees = this.convertDeptsNew(depts);
        return trees;
    }

    @Override
    public Integer findDeptsCount(Dept dept) {
        LambdaQueryWrapper<Dept> query = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(dept.getTenantId())) {
            query.eq(Dept::getTenantId, dept.getTenantId());
        }
        if(StringUtils.isNotBlank(dept.getDeptName())){
            query.eq(Dept::getDeptName,dept.getDeptName());
        }
        query.eq(Dept::getParentId,"0");
        query.eq(Dept::getDeletedFlg,"0");
        query.orderByAsc(Dept::getOrderNum);
        return this.baseMapper.selectList(query).size();
    }

    @Override
    public DeptTreeNew<Dept> findDeptsA(Dept dept) {
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(dept.getDeptName())) {
            queryWrapper.lambda().like(Dept::getDeptName, dept.getDeptName());
        }
        if (StringUtils.isNotBlank(dept.getParentId())) {
            queryWrapper.lambda().eq(Dept::getParentId, dept.getParentId());
        }
        if (StringUtils.isNotBlank(dept.getTenantId())) {
            queryWrapper.lambda().eq(Dept::getTenantId, dept.getTenantId());
        }
        if (StringUtils.isNotBlank(dept.getStatus())) {
            queryWrapper.lambda().eq(Dept::getStatus, dept.getStatus());
        }
        queryWrapper.lambda().eq(Dept::getDeletedFlg, FebsConstant.VALID);
        queryWrapper.lambda().orderByAsc(Dept::getOrderNum);
        List<Dept> depts = this.baseMapper.selectList(queryWrapper);
        List<DeptTreeNew<Dept>> trees = this.convertDeptsNew(depts);
        return TreeUtil.buildDeptTreeNew(trees);
    }

    @Override
    public Object findDeptsB(Dept dept) {
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(dept.getDeptName())) {
            queryWrapper.lambda().like(Dept::getDeptName, dept.getDeptName());
        }
        queryWrapper.lambda().eq(Dept::getDeletedFlg, FebsConstant.VALID);
        queryWrapper.lambda().orderByAsc(Dept::getOrderNum);
        List<Dept> depts = this.baseMapper.selectList(queryWrapper);

        LambdaQueryWrapper<Dept> query = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(dept.getTenantId())) {
            query.eq(Dept::getTenantId, dept.getTenantId());
        }
        query.eq(Dept::getParentId,"0");
        query.eq(Dept::getDeletedFlg,"0");
        query.orderByAsc(Dept::getOrderNum);
        List<Dept> pDepts = this.baseMapper.selectList(query);

        return this.buildTree(pDepts,depts);
    }

    @Override
    public List<Dept> findDepts(Dept dept, QueryRequest request) {
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(dept.getDeptName())){
            queryWrapper.lambda().eq(Dept::getDeptName, dept.getDeptName());
        }
        queryWrapper.lambda().eq(Dept::getDeletedFlg, FebsConstant.VALID);
        SortUtil.handleWrapperSort(request, queryWrapper, "orderNum", FebsConstant.ORDER_ASC, true);
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    @Transactional
    public void createDept(Dept dept) {
        if(StringUtils.isEmpty(dept.getParentId())){
            dept.setParentId("0");
        }
        dept.setCreateTime(new Date());
        this.save(dept);
    }

    /**
     * 更新部门
     *
     * @param dept 部门对象
     * @author qiny
     * @date 2019-07-23
     */
    @Override
    @Transactional
    public void updateDept(Dept dept) {
        dept.setModifyTime(new Date());
        this.baseMapper.updateById(dept);
    }

    /**
     * 新的部门删除实现方法
     *
     * @param ids 部门 ID集合
     * @param
     */
    @Override
    @Transactional
    public void updateDeptDeletedFlg(String ids, Dept dept) {
        List<String> idlist = getId(ids);
        this.baseMapper.update(dept, new LambdaQueryWrapper<Dept>().in(Dept::getDeptId, idlist));
    }

    private List<MenuTree<Dept>> convertDepts(List<Dept> depts, String parentId){
        List<MenuTree<Dept>> trees = new ArrayList<>();
        depts.forEach(dept -> {
            MenuTree<Dept> tree = new MenuTree<>();
            tree.setId(String.valueOf(dept.getDeptId()));
            tree.setParentId(parentId);
            tree.setTitle(dept.getDeptName());
            tree.setHasParent(true);
            tree.setData(dept);
            trees.add(tree);
        });
        return trees;
    }

    private List<DeptTree<Dept>> convertDepts(List<Dept> depts){
        List<DeptTree<Dept>> trees = new ArrayList<>();
        depts.forEach(dept -> {
            String statusText = !"1".equals(dept.getStatus())?"(禁用)":"";
            DeptTree<Dept> tree = new DeptTree<>();
            tree.setId(String.valueOf(dept.getDeptId()));
            tree.setType(String.valueOf(dept.getDeptType()));
            tree.setParentId(String.valueOf(dept.getParentId()));
            tree.setName(dept.getDeptName()+statusText);
            tree.setData(dept);
            trees.add(tree);
        });
        return trees;
    }

    private List<DeptTreeNew<Dept>> convertDeptsNew(List<Dept> depts){
        List<DeptTreeNew<Dept>> trees = new ArrayList<>();
        depts.forEach(dept -> {
            String statusText = !"1".equals(dept.getStatus())?"(禁用)":"";
            DeptTreeNew<Dept> tree = new DeptTreeNew<>();
            tree.setId(String.valueOf(dept.getDeptId()));
            tree.setType(String.valueOf(dept.getDeptType()));
            tree.setParentId(String.valueOf(dept.getParentId()));
            tree.setName(dept.getDeptName()+statusText);
            tree.setTitle(dept.getDeptName()+statusText);
            tree.setCode(dept.getDeptCode());
            tree.setBusinessCode(dept.getBusinessCode());
            tree.setOrderNum(dept.getOrderNum());
            tree.setStatus(dept.getStatus());
            tree.setData(dept);
            trees.add(tree);
        });
        return trees;
    }

    /**
     * 获取级联id
     *
     * @param ids
     * @return
     */
    private List<String> getId(String ids) {
        String[] idArrs = ids.split(StringPool.COMMA);
        //传的id
        List<String> idlist = Arrays.asList(idArrs);
        List arrList = new ArrayList(idlist);

        //临时list ，存方存在下级元素的id
        List<String> tempList = new ArrayList<>();
        List<Dept> depts = baseMapper.selectList(new LambdaQueryWrapper<Dept>().in(Dept::getParentId, arrList));
        if (depts != null && !depts.isEmpty()) {
            //根据parentid查询到的id 主要是判断是否存在子元素。
            for (Dept dept : depts) {
                tempList.add(String.valueOf(dept.getDeptId()));
            }
            tempList.forEach((str) -> arrList.add(str));
        }

        while (depts != null && !depts.isEmpty()) {
            depts = baseMapper.selectList(new LambdaQueryWrapper<Dept>().in(Dept::getParentId, tempList));

            if (depts != null && !depts.isEmpty()) {
                //根据parentid查询到的id 主要是判断是否存在子元素。
                tempList.clear();
                for (Dept dept : depts) {
                    tempList.add(String.valueOf(dept.getDeptId()));
                }
                arrList.addAll(tempList);
            }
        }
        arrList.forEach(x -> System.out.println(x));
        return arrList;
    }

    /**
     * 部门excel导出
     *
     * @param dept
     * @param response
     * @author qiny
     * @date 2019-07-24
     */
    @Override
    public void exportDepts(QueryRequest request, Dept dept, HttpServletResponse response) {
        // 1.创建一个workbook，对应一个Excel文件
        HSSFWorkbook wb = new HSSFWorkbook();
        // 2.在workbook中添加一个sheet，对应Excel中的一个sheet
        HSSFSheet sheet = wb.createSheet("部门信息");
        // 3.在sheet中添加表头第0行，老版本poi对excel行数列数有限制short
        HSSFRow row = sheet.createRow(0);
        // 4.创建单元格，设置值表头，设置表头居中
        HSSFCellStyle style = wb.createCellStyle();

        // 设置表头
        HSSFCell cell = row.createCell(0);
        cell.setCellValue("部门名称");
        cell.setCellStyle(style);

        cell = row.createCell(1);
        cell.setCellValue("部门编号");
        cell.setCellStyle(style);

        cell = row.createCell(2);
        cell.setCellValue("创建人");
        cell.setCellStyle(style);

        cell = row.createCell(3);
        cell.setCellValue("创建时间");
        cell.setCellStyle(style);

        cell = row.createCell(4);
        cell.setCellValue("更新人");
        cell.setCellStyle(style);

        cell = row.createCell(5);
        cell.setCellValue("修改时间");
        cell.setCellStyle(style);

        cell = row.createCell(6);
        cell.setCellValue("删除人");
        cell.setCellStyle(style);

        cell = row.createCell(7);
        cell.setCellValue("删除时间");
        cell.setCellStyle(style);

        cell = row.createCell(8);
        cell.setCellValue("删除标记");
        cell.setCellStyle(style);

        String fileName = "部门信息表" + (new SimpleDateFormat("yyyyMMddHHmmss")).format(new Date());
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            List<Dept> lists = this.baseMapper.exportDepts(dept);
            // 循环将数据写入Excel
            for (int i = 0; i < lists.size(); i++) {
                row = sheet.createRow(i + 1);
                Dept temp = lists.get(i);
                // 创建单元格，设置值
                row.createCell(0).setCellValue(converNull(temp.getDeptName()));
                //if ("0".equals(converNull(temp.getOutsFlg()))) {
                //    row.createCell(1).setCellValue("本工");
                //} else if ("1".equals(converNull(temp.getOutsFlg()))) {
                //    row.createCell(1).setCellValue("外包");
                //}
                row.createCell(1).setCellValue(converNull(temp.getDeptCode()));
                row.createCell(2).setCellValue(converNull(temp.getCreatedBy()));
                row.createCell(3).setCellValue(converNull(temp.getCreateTime()));
                row.createCell(4).setCellValue(converNull(temp.getUpdatedBy()));
                row.createCell(5).setCellValue(converNull(temp.getModifyTime()));
                row.createCell(6).setCellValue(converNull(temp.getDeletedBy()));
                row.createCell(7).setCellValue(converNull(temp.getDeletedTime()));
                if ("0".equals(converNull(temp.getDeletedFlg()))) {
                    row.createCell(8).setCellValue("未删除");
                } else if ("1".equals(converNull(temp.getDeletedFlg()))) {
                    row.createCell(1).setCellValue("已删除");
                }
            }

            wb.write(os);
            byte[] content = os.toByteArray();
            InputStream is = new ByteArrayInputStream(content);
            // 设置response参数，可以打开下载页面
            response.reset();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + new String((fileName + ".xls").getBytes("GB2312"), StandardCharsets.ISO_8859_1));
            ServletOutputStream out = response.getOutputStream();
            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;

            try {
                bis = new BufferedInputStream(is);
                bos = new BufferedOutputStream(out);
                byte[] buff = new byte[2048];
                int bytesRead;
                // Simple read/write loop.
                while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                    bos.write(buff, 0, bytesRead);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (bis != null) {
                    bis.close();
                }
                if (bos != null) {
                    bos.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * null 转换
     *
     * @param obj
     * @return 返回字符串
     */
    private static String converNull(Object obj) {
        return Optional.ofNullable(obj).map(Object::toString).orElse("");
    }

    @Override
    public DeptTree<Dept> findDeptEletree(Dept dept) {
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();

        queryWrapper.lambda().orderByAsc(Dept::getOrderNum);
        queryWrapper.lambda().eq(Dept::getDeletedFlg, FebsConstant.VALID);
        List<Dept> menus = this.baseMapper.selectList(queryWrapper);
        List<DeptTree<Dept>> trees = this.convertDepts(menus);

        return TreeUtil.buildDeptEleTree(trees);
    }

    private List<Map<String,Object>> buildTree(List<Dept> pDepts,List<Dept> depts){
        List<Map<String,Object>> tree = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(pDepts)){
            pDepts.forEach(m->{
                Map<String,Object> map = new HashMap<>();
                map.put("id",m.getDeptId());
                map.put("name",m.getDeptName());
                List<Map<String,Object>> children = this.buildChildren(depts,m.getDeptId());
                map.put("children",children);
                tree.add(map);
            });
        }
        return tree;
    }

    private List<Map<String,Object>> buildChildren(List<Dept> list,String pid){
        List<Map<String,Object>> empty = new ArrayList<>();
        for(Dept m:list){
            Map<String,Object> child = new HashMap<>();
            if(m.getParentId().equals(pid)){
                child.put("id",m.getDeptId());
                child.put("name",m.getDeptName());
                child.put("children",buildChildren(list,m.getDeptId()));
                empty.add(child);
            }
        }
        if(empty.size()>0){
            return empty;
        }else{
            return null;
        }
    }

}

